﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using DevExpress.XtraEditors;
using System.Configuration;
using DevExpress.XtraCharts;
using FAMailUtils.MailGun;
using FAGateway.Common;
using RestSharp;

namespace FAGateway
{
    public partial class frmGateway : DevExpress.XtraEditors.XtraForm
    {
        SendMail sendmail = new SendMail(ConfigurationManager.AppSettings["api-key"]);
        DomainUtils domainUtils = new DomainUtils(ConfigurationManager.AppSettings["api-key"]);
        string AccessKey = System.Configuration.ConfigurationManager.AppSettings["AccessKey"];
        string SecrectKey = System.Configuration.ConfigurationManager.AppSettings["SecrectKey"];

        log4net.ILog logs_error = log4net.LogManager.GetLogger("ErrorRollingLogFileAppender");
        log4net.ILog logs_info = log4net.LogManager.GetLogger("InfoRollingLogFileAppender");
        log4net.ILog logs_scan = log4net.LogManager.GetLogger("ScanEmailAppender");
        log4net.ILog logs_traching = log4net.LogManager.GetLogger("TrackingEmailAppender");
        static readonly object syncRoot = new object();
        static readonly object syncRoot_check = new object();
        AmazonCommon vEmail;
        double TotalSend, SendRate = 5, Max24HourRate;

        public frmGateway()
        {
            InitializeComponent();
        }

        private void frmGateway_Load(object sender, EventArgs e)
        {
            txtThread.Text = ConfigurationManager.AppSettings["DefaultThread"];
            bgw_sendMail.DoWork += bgw_sendMail_DoWork;
            vEmail = new AmazonCommon(AccessKey, SecrectKey);
            //vEmail.GetQuotaInfo(out TotalSend, out SendRate, out Max24HourRate);
            txtSpeed.Text = SendRate + "";
            marqueeProgressBarControl1.Visible = false;
            txtBounceTopic.Text = ConfigurationManager.AppSettings["BounceTopic"];
            txtComplainTopic.Text = ConfigurationManager.AppSettings["ComplainTopic"];
            tabCheckResult.PageVisible = ConfigurationManager.AppSettings["isShowCheckResult"] + "" == "1";
        }

        private void btnDStart_Click(object sender, EventArgs e)
        {
            btnDStart.Enabled = false;
            btnDStop.Enabled = true;
            txtSecond.Enabled = false;

            timer_Dashboard.Interval = Convert.ToInt32(txtSecond.Text) * 1000;
            timer_Dashboard.Start();
        }

        private void LoadDashBoard()
        {
            vEmail.GetQuotaInfo(out TotalSend, out SendRate, out Max24HourRate);
            chartControl1.Series.Clear();
            Series series = new Series();
            SeriesPoint point = new SeriesPoint();
            point.Values = new double[] { TotalSend };
            point.Argument = "TotalSend";
            series.ChangeView(ViewType.Bar);
            series.Points.Add(point);
            chartControl1.Series.Add(series);

            series = new Series();
            point = new SeriesPoint();
            point.Values = new double[] { Max24HourRate };
            point.Argument = "Limit24Hours";
            series.ChangeView(ViewType.Bar);
            series.Points.Add(point);
            chartControl1.Series.Add(series);
        }

        private void timer_Dashboard_Tick(object sender, EventArgs e)
        {
            if (bgw_Dashboard.IsBusy) return;
            bgw_Dashboard.RunWorkerAsync();
        }

        private void btnDStop_Click(object sender, EventArgs e)
        {
            btnDStart.Enabled = true;
            btnDStop.Enabled = false;
            txtSecond.Enabled = true;
            timer_Dashboard.Stop();
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            bgw_sendMail.CancelAsync();
            btnStart.Enabled = true;
            btnStop.Enabled = false;
            timer_sendMail.Stop();
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            timer_sendMail.Enabled = true;
            btnStop.Enabled = true;
            btnStart.Enabled = false;
            timer_sendMail.Start();
        }

        void bgw_sendMail_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                List<SendItem> items = DataUtils.GetMail2Send();
                int cnt = 0;
                int totalCnt = items.Count;

                Parallel.ForEach(items.AsParallel(), new ParallelOptions { MaxDegreeOfParallelism = Convert.ToInt32(txtThread.Text) }, item =>
                {
                    int i = DataUtils.CheckMailConfig(item.From.Split('@')[1]);
                    if (i > 0)
                    {
                        SendResult sendItem = sendmail.SendHtmlMessage(item.From.Split('@')[1] + "", item.SenderName, item.From, item.To, item.Subject, item.Body, true);
                        sendItem.item_id = item.id;
                        string log = DateTime.Now + "-> Status: " + sendItem.IsSent + ", id:" + sendItem.id + ", MailTo: " + item.To + ", mailFrom: " + item.From + ", Name: " + item.CustomerName;
                        logs_info.Info(log);
                        //memoEdit1.Text = log + Environment.NewLine + memoEdit1.Text;
                        DataUtils.UpdateSendItem(sendItem);
                    }
                    lock (syncRoot) cnt++;
                });

            }
            catch (Exception ex)
            {
                logs_error.Error("bgw_sendMail_DoWork-", ex);
                //memoEdit2.Text += DateTime.Now.ToString() + ex.Message + Environment.NewLine + memoEdit2.Text;
            }
        }

        private void timer_sendMail_Tick(object sender, EventArgs e)
        {
            if (bgw_sendMail.IsBusy) return;
            bgw_sendMail.RunWorkerAsync();
        }

        private void btnCRStop_Click(object sender, EventArgs e)
        {
            btnCRStart.Enabled = true;
            btnCRStop.Enabled = false;
            txtCRSecond.Enabled = true;
            timer_CheckResult.Stop();
            timer_tracking.Stop();
        }

        private void btnCRStart_Click(object sender, EventArgs e)
        {
            btnCRStart.Enabled = false;
            btnCRStop.Enabled = true;
            txtCRSecond.Enabled = false;

            timer_CheckResult.Interval = Convert.ToInt32(txtCRSecond.Text) * 1000;
            timer_CheckResult.Start();


            //timer_tracking.Interval = Convert.ToInt32(txtCRSecond.Text) * 1000;
            //timer_tracking.Start();
        }

        private void timer_CheckResult_Tick(object sender, EventArgs e)
        {
            if (bgw_Check.IsBusy) return;
            bgw_Check.RunWorkerAsync();
        }

        private void bgw_Check_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {

                DataUtils.CheckDomainLimit();
                /*
                int CheckResultBackCount = 0;
                int.TryParse(ConfigurationManager.AppSettings["CheckResultBackCount"] + "", out CheckResultBackCount);
                if (CheckResultBackCount == 0) CheckResultBackCount = 1;


                DataTable dtDomain = DataUtils.GetDomainSenderTrackingDelivery();
                if (dtDomain != null && dtDomain.Rows.Count > 0)
                {
                    List<string> items = new List<string>();
                    foreach (DataRow row in dtDomain.Rows)
                        items.Add(row["domain"] + "");
                    int cnt = 0;
                    Parallel.ForEach(items.AsParallel(), new ParallelOptions { MaxDegreeOfParallelism = Convert.ToInt32(5) }, domain =>
                    {
                        //txtCRInfoLogs.Text += DateTime.Now + "tracking domain: " + row["domain"] + Environment.NewLine;
                        logs_traching.Info("tracking domain: " + domain);
                        Logs result = sendmail.GetLogs(domain, CheckResultBackCount);
                        if (result.isGetOK)
                        {
                            logs_traching.Info("tracking " + result.items.Count().ToString("#,##") + " items");
                            //txtCRInfoLogs.Text += DateTime.Now + "tracking " + result.items.Count().ToString("#,##") + " items" + Environment.NewLine;
                            foreach (var item in result.items)
                            {
                                DataUtils.UpdateSendItemResult(item);
                                logs_traching.Info("tracking status: " + item.Event + " item:" + item.from + " to: " + item.to + "");
                            }
                            UpdateSendItem(result, domain);
                        }
                        else
                        {
                            string logs = "bgw_Check_DoWork" + Environment.NewLine + result.message;
                            logs_error.Error(logs);
                            //txtCRErrorLogs.Text += Environment.NewLine + logs;
                        }
                        lock (syncRoot_check) cnt++;
                    });
                }*/
            }
            catch (Exception ex)
            {
                txtCRErrorLogs.Text = DateTime.Now + ":" + ex.Message + Environment.NewLine + txtCRErrorLogs.Text;
            }
        }
        public void UpdateSendItem(Logs result, string domain)
        {
            if (!string.IsNullOrEmpty(result.paging.next))
            {
                result = sendmail.GetLogNextPage(result.paging.next, domain);
                if (result.isGetOK && result.items.Count > 0)
                {
                    foreach (var item in result.items)
                    {
                        DataUtils.UpdateSendItemResult(item);
                        logs_info.Info("tracking status: " + item.Event + " item:" + item.from + " to: " + item.to + "");
                    }
                    UpdateSendItem(result, domain);
                }
            }
        }
        public void UpdateSendItem(TrackingLogs result, string domain)
        {
            if (!string.IsNullOrEmpty(result.paging.next))
            {
                result = sendmail.GetTrackingLogNextPage(result.paging.next, domain);
                if (result.isGetOK && result.items.Count > 0)
                {
                    foreach (var item in result.items)
                    {
                        DataUtils.UpdateSendItemResult(item);
                        logs_info.Info("tracking status: " + item.Event + " recipient: " + item.recipient + "");
                    }
                    UpdateSendItem(result, domain);
                }
            }
        }
        private void bgw_Verify_DoWork(object sender, DoWorkEventArgs e)
        {
            DataUtils.UpdateBounceResultToCustomer();
            DataTable domains = DataUtils.GetDomainToVerifyEmail();
            EmailValidate verify = new EmailValidate(ConfigurationManager.AppSettings["publicApi-key"]);
            foreach (DataRow r in domains.Rows)
            {
                if (ConfigurationManager.AppSettings["publicApi-key"].IndexOf(r[0] + "") < 0)
                {
                    logs_scan.Info("verify domain: " + r[0]);
                    if (!verify.GetValidate("verify@" + r[0]).is_valid)
                    {
                        object obj = DataUtils.UpdateEmailByDomainFail(r[0] + "");
                        logs_scan.Info("verify domain: fails " + obj + " items");
                    }
                    else
                    {
                        object obj = DataUtils.UpdateEmailByDomainOK(r[0] + "");
                        logs_scan.Info("verify domain: ok " + obj + " items");
                    }
                }
            }
        }

        private void bgw_Dashboard_DoWork(object sender, DoWorkEventArgs e)
        {
            LoadDashBoard();
        }

        private void btnVStart_Click(object sender, EventArgs e)
        {
            btnVStart.Enabled = false;
            btnVStop.Enabled = true;
            txtVSecond.Enabled = false;

            timer_Verify.Interval = Convert.ToInt32(txtSecond.Text) * 1000;
            timer_Verify.Start();
        }

        private void btnVStop_Click(object sender, EventArgs e)
        {

            btnVStart.Enabled = true;
            btnVStop.Enabled = false;
            txtVSecond.Enabled = true;
            timer_Verify.Stop();
        }

        private void timer_Verify_Tick(object sender, EventArgs e)
        {

            if (bgw_Verify.IsBusy) return;
            bgw_Verify.RunWorkerAsync();
        }

        private void btnLoad_Click(object sender, EventArgs e)
        {
            if (bgw_AmazonEmailVerified.IsBusy) return;

            marqueeProgressBarControl1.Visible = true;
            bgw_AmazonEmailVerified.RunWorkerAsync();
        }

        private void bgw_AmazonEmailVerified_DoWork(object sender, DoWorkEventArgs e)
        {
            List<EmailVerified> list = vEmail.ListEmailVerifiedWithNotification();
            e.Result = list;
        }

        private void bgw_AmazonEmailVerified_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            marqueeProgressBarControl1.Visible = false;
            gridControl1.DataSource = e.Result;
        }

        private void gridView1_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Right)
            {
                EmailVerified row = (EmailVerified)gridView1.GetFocusedRow();
                if (row != null)
                {
                    setBounceTopicToolStripMenuItem.Visible = !row.isSetBounceTopic;
                    unsetBounceTopicToolStripMenuItem.Visible = row.isSetBounceTopic;
                    setComplainTopicToolStripMenuItem.Visible = !row.isSetComplainTopic;
                    unsetComplainTopicToolStripMenuItem.Visible = row.isSetComplainTopic;
                }
            }
        }

        private void setBounceTopicToolStripMenuItem_Click(object sender, EventArgs e)
        {
            EmailVerified row = (EmailVerified)gridView1.GetFocusedRow();
            if (row != null)
            {
                if (vEmail.SetBounceTopic(row.Email, txtBounceTopic.Text))
                    MessageBox.Show("Set Successfull");
                else MessageBox.Show("Set fail");
            }
        }

        private void unsetBounceTopicToolStripMenuItem_Click(object sender, EventArgs e)
        {
            EmailVerified row = (EmailVerified)gridView1.GetFocusedRow();
            if (row != null)
            {
                if (vEmail.SetBounceTopic(row.Email, null))
                    MessageBox.Show("Set Successfull");
                else MessageBox.Show("Set fail");
            }
        }

        private void setComplainTopicToolStripMenuItem_Click(object sender, EventArgs e)
        {
            EmailVerified row = (EmailVerified)gridView1.GetFocusedRow();
            if (row != null)
            {
                if (vEmail.SetComplainTopic(row.Email, txtComplainTopic.Text))
                    MessageBox.Show("Set Successfull");
                else MessageBox.Show("Set fail");
            }
        }

        private void unsetComplainTopicToolStripMenuItem_Click(object sender, EventArgs e)
        {
            EmailVerified row = (EmailVerified)gridView1.GetFocusedRow();
            if (row != null)
            {
                if (vEmail.SetComplainTopic(row.Email, null))
                    MessageBox.Show("Set Successfull");
                else MessageBox.Show("Set fail");
            }
        }

        private void btnRegister_Click(object sender, EventArgs e)
        {
            if (txtEmailRegister.Text.Trim() == "") { MessageBox.Show("Input Email to Retister"); txtEmailRegister.Focus(); return; }
            if (!Common.EmailTools.IsEmail(txtEmailRegister.Text.Trim())) { MessageBox.Show("Input Email is not format correct"); txtEmailRegister.Focus(); return; }
            if (vEmail.RegisterEmail(txtEmailRegister.Text.Trim()))
            {
                MessageBox.Show("Register OK! Please check mail to confirm.");
            }
        }

        private void simpleButton1_Click(object sender, EventArgs e)
        {
            frmCheckMail check = new frmCheckMail();
            check.Show();
        }

        private void btnDomain_Start_Click(object sender, EventArgs e)
        {

            btnDomain_Start.Enabled = false;
            btnDomain_Stop.Enabled = true;
            txtDomain_Interval.Enabled = false;
            mqDomain.Visible = true;

            timer_domain.Interval = Convert.ToInt32(txtDomain_Interval.Text) * 1000;
            timer_domain.Start();
        }

        private void btnDomain_Stop_Click(object sender, EventArgs e)
        {

            btnDomain_Start.Enabled = true;
            btnDomain_Stop.Enabled = false;
            txtDomain_Interval.Enabled = true;
            mqDomain.Visible = false;
            timer_domain.Stop();
        }

        private void timer_domain_Tick(object sender, EventArgs e)
        {
            if (bgw_domain.IsBusy) return;
            bgw_domain.RunWorkerAsync();
        }

        private void bgw_domain_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                DomainList source = domainUtils.GetDomains(true);
                e.Result = source;
            }
            catch (Exception ex)
            {
                logs_error.Error("bgw_domain_DoWork", ex);
            }
            finally
            {// mqDomain.Visible = false; 
            }
        }

        private void bgw_domain_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            try
            {
                if (e.Result != null && ((DomainList)e.Result).isGetOK && ((DomainList)e.Result).items != null)
                {
                    DomainList source = ((DomainList)e.Result);
                    foreach (var item in source.items)
                    {
                        DataUtils utils = new DataUtils();
                        if (item.detail != null)
                        {
                            foreach (var obj in item.detail.sending_dns_records)
                                if (obj.valid == "valid")
                                    utils.UpdateMailConfig(item);
                        }
                    }
                }
            }

            catch (Exception ex)
            {
                logs_error.Error("bgw_domain_RunWorkerCompleted", ex);
            }
        }

        private void btnDomain_Click(object sender, EventArgs e)
        {
            gridControl2.DataSource = domainUtils.GetDomains(true).items;
        }

        private void bgw_tracking_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {

                int CheckResultBackCount = 0;
                int.TryParse(ConfigurationManager.AppSettings["CheckResultBackCount"] + "", out CheckResultBackCount);
                if (CheckResultBackCount == 0) CheckResultBackCount = 1;


                DataTable dtDomain = DataUtils.GetDomainSenderTrackingOpenClick();
                if (dtDomain != null && dtDomain.Rows.Count > 0)
                {
                    List<string> items = new List<string>();
                    foreach (DataRow row in dtDomain.Rows)
                        items.Add(row["domain"] + "");
                    int cnt = 0;
                    Parallel.ForEach(items.AsParallel(), new ParallelOptions { MaxDegreeOfParallelism = Convert.ToInt32(5) }, domain =>
                    {
                        //txtCRInfoLogs.Text += DateTime.Now + "tracking domain: " + row["domain"] + Environment.NewLine;
                        logs_traching.Info("tracking domain: " + domain);
                        TrackingLogs result = sendmail.GetLogsTracking(domain, CheckResultBackCount);
                        if (result.isGetOK)
                        {
                            logs_traching.Info("tracking " + result.items.Count().ToString("#,##") + " items");
                            //txtCRInfoLogs.Text += DateTime.Now + "tracking " + result.items.Count().ToString("#,##") + " items" + Environment.NewLine;
                            foreach (var item in result.items)
                            {
                                if (item.messageId + "" != "")
                                {
                                    DataUtils.UpdateSendItemResult(item);
                                    logs_traching.Info("tracking status: " + item.Event + " recipient: " + item.recipient + "");
                                }
                            }
                            UpdateSendItem(result, domain);
                        }
                        else
                        {
                            string logs = "bgw_Check_DoWork" + Environment.NewLine + result.message;
                            logs_error.Error(logs);
                            //txtCRErrorLogs.Text += Environment.NewLine + logs;
                        }
                        lock (syncRoot_check) cnt++;
                    });
                }
            }
            catch (Exception ex)
            {
                txtCRErrorLogs.Text = DateTime.Now + ":" + ex.Message + Environment.NewLine + txtCRErrorLogs.Text;
            }
        }

        private void timer_tracking_Tick(object sender, EventArgs e)
        {
            if (bgw_tracking.IsBusy) return;
            bgw_tracking.RunWorkerAsync();
        }

        private void btn_DomainStatus_Search_Click(object sender, EventArgs e)
        {
            DataTable source= DataUtils.GetDomainSendStatus(txt_DomainStatus_Key.Text);
            gridControl3.DataSource = source;
            gridView3.ExpandAllGroups();
        }

        private void khóaToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DataRow row = gridView3.GetFocusedDataRow();
            if (row != null)
            {
                if (row["status_0N_1W_2B"] + "" != "2")
                {
                    DataUtils.BanDomain(row["Domain"], true);
                    MessageBox.Show("Ban successfull");
                }
                else MessageBox.Show("Domain was baned!");
            }
        }

        private void mởKhóaToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DataRow row = gridView3.GetFocusedDataRow();
            if (row != null)
            {
                if (row["status_0N_1W_2B"] + "" == "2")
                {
                    DataUtils.BanDomain(row["Domain"], false);
                    MessageBox.Show("UnBan successfull");
                }
                else MessageBox.Show("Domain is in Normal Status!");
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            IRestResponse result = CreateRoute();
            string sss = result.Content;
        }
        public static IRestResponse CreateRoute()
        {
            RestClient client = new RestClient();
            client.BaseUrl = "https://api.mailgun.net/v2";
            client.Authenticator =
                    new HttpBasicAuthenticator("api",
                                               "key-0hvxsu9bubvdc9060do5rn44z3masyw0");
            RestRequest request = new RestRequest();
            request.Resource = "routes";
            request.AddParameter("priority", 0);
            request.AddParameter("description", "wecarevietnam route");
            request.AddParameter("expression",
                                 "match_recipient('.*@wecarevietnam.com')");
            request.AddParameter("action",
                                 "forward('http://famails.com/tracking/inbound.aspx')");
            //request.AddParameter("action", "stop()");
            request.Method = Method.POST;
            return client.Execute(request);
        }
    }
}